package top.letscode.adclicker.driver;

import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.UnexpectedAlertBehaviour;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeDriverService;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.WebDriverWait;

import top.letscode.adclicker.executor.ExecutorAttachment;
import top.letscode.adclicker.executor.ExecutorThreadLocal;
import top.letscode.adclicker.store.SimpleDataStore;
import top.letscode.adclicker.util.Constants;
import top.letscode.adclicker.util.RandomUtil;

public class ChromeDriverFactory {

  private static final File ALERT_CONTROL = new File("C:/chrome_alert_control2");
  private static final File ALEXA_EXTENSION = new File("c:/alexa");

  static {
    try {
      // set chrome driver path
      URI uri = ChromeDriverFactory.class.getResource("/chromedriver.exe").toURI();
      File file = new File(uri);
      System.setProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY, file.getAbsolutePath());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public static WebDriver newInstance(String type) {
    DesiredCapabilities capabilities = DesiredCapabilities.chrome();
    if (Constants.UNION_TYPE_WEB.equals(type)) {
      capabilities.setCapability(ChromeOptions.CAPABILITY, getWebOptions());
    }

    if (Constants.UNION_TYPE_MOBILE.equals(type)) {
      capabilities.setCapability(ChromeOptions.CAPABILITY, getMobileOptions());
    }
    capabilities.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR,
        UnexpectedAlertBehaviour.ACCEPT);

    WebDriver webDriver = new ChromeDriver(capabilities);
    webDriver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS);

    ExecutorAttachment attachment = new ExecutorAttachment();
    attachment.setWebDriverWait(new WebDriverWait(webDriver, 20, 200));
    ExecutorThreadLocal.set(attachment);

    return webDriver;
  }

  private static ChromeOptions getWebOptions() {
    ChromeOptions options = new ChromeOptions();
    options.addArguments("–ignore-certificate-errors", "test-type", "--disable-popup-blocking");
    options.addArguments("-start-maximized");
    List<String> userAgents =
        SimpleDataStore.getFileLines(Constants.STORE_FILE_LINES, "/userAgent.txt");
    options.addArguments("--user-agent=" + RandomUtil.random(userAgents).trim());
    if (ALERT_CONTROL.exists()) {
      options.addArguments("load-extension=" + ALERT_CONTROL.getAbsolutePath());
    }
    if (ALEXA_EXTENSION.exists()) {
      options.addArguments("load-extension=" + ALEXA_EXTENSION.getAbsolutePath());
    }

    return options;
  }

  private static Map<String, Object> getMobileEmulation() {
    Map<String, Object> mobileEmulation = new HashMap<String, Object>();

    List<String> deviceNameList =
        SimpleDataStore.getFileLines(Constants.STORE_FILE_LINES, "/deviceName.txt");
    String deviceName = RandomUtil.random(deviceNameList);
    String[] arr = deviceName.split("\\$\\$");

    if (arr.length == 1) {// 浏览器预设机型
      mobileEmulation.put("deviceName", deviceName);
    } else {// 自定义机型
      Map<String, Object> deviceMetrics = new HashMap<String, Object>();
      deviceMetrics.put("width", Integer.parseInt(arr[1]));
      deviceMetrics.put("height", Integer.parseInt(arr[2]));
      deviceMetrics.put("pixelRatio", 3.0);

      mobileEmulation.put("deviceMetrics", deviceMetrics);
      mobileEmulation.put("userAgent", arr[3]);
    }

    return mobileEmulation;
  }

  private static Map<String, Object> getMobileOptions() {
    Map<String, Object> chromeOptions = new HashMap<String, Object>();
    chromeOptions.put("mobileEmulation", getMobileEmulation());
    List<String> args = new ArrayList<String>();
    args.add("test-type");
    args.add("ignore-certificate-errors");
    if (ALERT_CONTROL.exists()) {
      args.add("load-extension=" + ALERT_CONTROL.getAbsolutePath());
    }
    chromeOptions.put("args", args);

    return chromeOptions;
  }
}
